﻿using Microsoft.Office.Server.Search.Administration;
using Microsoft.SharePoint;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Xml.Linq;

namespace SPSDeploy.Extensions.Extensions
{
    /// <summary>
    /// Query suggestions extensions
    /// </summary>
    internal static class QuerySuggestionsExtension
    {

        // Private members
        private static Guid empty = Guid.Empty;

        /// <summary>
        /// Compare query suggestion instances
        /// </summary>
        /// <param name="element"></param>
        /// <param name="item"></param>
        /// <returns></returns>
        internal static bool Equals(XElement element, LanguageResourcePhrase item)
        {
            return element.Attribute("culture").Value == item.Culture.ToString() &&
                element.Attribute("type").Value == item.Type.ToString() &&
                element.Attribute("phrase").Value == item.Phrase &&
                element.Attribute("mapping").Value == (item.Mapping ?? string.Empty) &&
                element.Attribute("tenantId").Value == item.TenantId.ToString() &&
                element.Attribute("siteId").Value == item.SiteId.ToString() &&
                element.Attribute("webId").Value == item.WebId.ToString();
        }

        /// <summary>
        /// Return all query suggestion languange resources
        /// </summary>
        /// <param name="application"></param>
        /// <returns></returns>
        internal static List<LanguageResourcePhrase> GetAll(SearchServiceApplication application)
        {
            List<LanguageResourcePhrase> result = new List<LanguageResourcePhrase>();
            foreach (Ranking ranking in GetRankings(application))
                foreach (LanguageResource item in ranking.LanguageResources)
                {
                    AddLanguageResourcePhrases(result, item.QuerySuggestionsAlwaysSuggestList);
                    AddLanguageResourcePhrases(result, item.QuerySuggestionsBlockList);
                    AddLanguageResourcePhrases(result, item.QuerySuggestionsSubstitutions);
                }
            return result;
        }

        /// <summary>
        /// Add query suggestion phrase list
        /// </summary>
        /// <param name="resourceList"></param>
        /// <param name="phraseList"></param>
        private static void AddLanguageResourcePhrases(List<LanguageResourcePhrase> resourceList, LanguageResourcePhraseList phraseList)
        {
            foreach (LanguageResourcePhrase item in phraseList)
                resourceList.Add(item);
        }

        /// <summary>
        /// Return query suggestion rankings for all available owners
        /// </summary>
        /// <param name="application"></param>
        /// <returns></returns>
        internal static List<Ranking> GetRankings(SearchServiceApplication application)
        {
            List<Ranking> result = new List<Ranking>();
            using (SqlConnection cn = new SqlConnection(application.SearchAdminDatabase.DatabaseConnectionString))
            {
                cn.Open();
                SqlCommand cmd = new SqlCommand("SELECT DISTINCT TenantId, SiteId, WebId FROM dbo.MSSLanguageResources WITH (NOLOCK) WHERE [Type] IN (1, 2, 10) ORDER BY 1, 2, 3", cn) { CommandType = CommandType.Text };
                using (SqlDataReader r = cmd.ExecuteReader())
                    while (r.Read())
                    {
                        Guid tenantId = (Guid)r["TenantId"];
                        Guid siteId = (Guid)r["SiteId"];
                        Guid webId = (Guid)r["WebId"];
                        if (tenantId == empty && siteId == empty && webId == empty)
                            result.Add(new Ranking(application, new SearchObjectOwner(SearchObjectLevel.Ssa)));
                        else if (tenantId != empty && siteId != empty && webId == empty)
                            result.Add(new Ranking(application, new SearchObjectOwner(SearchObjectLevel.SPSite, new SPSite(siteId).RootWeb)));
                        else if (tenantId != empty && siteId != empty && webId != empty)
                            result.Add(new Ranking(application, new SearchObjectOwner(SearchObjectLevel.SPWeb, new SPSite(siteId).AllWebs[webId])));
                    }
            }
            return result;
        }

        /// <summary>
        /// Create query suggestion phrase
        /// </summary>
        /// <param name="element"></param>
        /// <param name="application"></param>
        internal static void Create(XElement element, SearchServiceApplication application)
        {
            Guid tenantId = new Guid(element.Attribute("tenantId").Value);
            Guid siteId = new Guid(element.Attribute("siteId").Value);
            Guid webId = new Guid(element.Attribute("webId").Value);
            Ranking ranking;
            if (tenantId == empty && siteId == empty && webId == empty)
                ranking = new Ranking(application, new SearchObjectOwner(SearchObjectLevel.Ssa));
            else if (tenantId != empty && siteId != empty && webId == empty)
                ranking = new Ranking(application, new SearchObjectOwner(SearchObjectLevel.SPSite, new SPSite(siteId).RootWeb));
            else
                ranking = new Ranking(application, new SearchObjectOwner(SearchObjectLevel.SPWeb, new SPSite(siteId).AllWebs[webId]));
            switch ((LanguageResourceType)Enum.Parse(typeof(LanguageResourceType), element.Attribute("type").Value))
            {
                case LanguageResourceType.QuerySuggestionAlwaysSuggest:
                    ranking.LanguageResources[element.Attribute("culture").Value].QuerySuggestionsAlwaysSuggestList.AddPhrase(empty, element.Attribute("phrase").Value, element.Attribute("mapping").Value);
                    break;
                case LanguageResourceType.QuerySuggestionBlockList:
                    ranking.LanguageResources[element.Attribute("culture").Value].QuerySuggestionsBlockList.AddPhrase(empty, element.Attribute("phrase").Value, element.Attribute("mapping").Value);
                    break;
                case LanguageResourceType.QuerySuggestionSubstitution:
                    ranking.LanguageResources[element.Attribute("culture").Value].QuerySuggestionsSubstitutions.AddPhrase(empty, element.Attribute("phrase").Value, element.Attribute("mapping").Value);
                    break;
            }
        }

    }
}